// Copyright 2004-present Facebook. All Rights Reserved.

package com.facebook.react;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.KeyEvent;

import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.PermissionListener;

import javax.annotation.Nullable;

/**
 * todo(0.54.3) rn 版本 更新是记得更新这里
 * 用来代替 {@link ReactActivityDelegate} 基于 react-native-0.54.3
 */
public class RNActivityDelegate {

    private final @Nullable Activity mActivity;
    private final @Nullable FragmentActivity mFragmentActivity;
    private @Nullable String mMainComponentName;

    protected @Nullable ReactRootView mReactRootView;
    private @Nullable DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
    private @Nullable PermissionListener mPermissionListener;
    private @Nullable Callback mPermissionsCallback;

    public RNActivityDelegate(Activity activity, @Nullable String mainComponentName) {
        mActivity = activity;
        mMainComponentName = mainComponentName;
        mFragmentActivity = null;
    }

    public RNActivityDelegate(
            FragmentActivity fragmentActivity,
            @Nullable String mainComponentName) {
        mFragmentActivity = fragmentActivity;
        mMainComponentName = mainComponentName;
        mActivity = null;
    }

    protected @Nullable Bundle getLaunchOptions() {
        Bundle bundle = mLaunchOptions;
        mLaunchOptions= null;
        return bundle;
    }

    protected ReactRootView createRootView() {
        ReactRootView view = mReactRootView;
        if(view == null){
            view = new ReactRootView(getContext());
        }
        return view;
    }

    /**
     * Get the {@link ReactNativeHost} used by this app. By default, assumes
     * {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
     * {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
     * does not implement {@code ReactApplication} or you simply have a different mechanism for
     * storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
     */
    protected ReactNativeHost getReactNativeHost() {
        return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
    }

    public ReactInstanceManager getReactInstanceManager() {
        return getReactNativeHost().getReactInstanceManager();
    }

    protected void onCreate(Bundle savedInstanceState) {
        isRunning = -1;
//        if (mMainComponentName != null) {
//            loadApp(mMainComponentName);
//        }
        mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
    }
    /**
     * @param appKey 为null 时取上次的
     */
    protected void loadApp(String appKey) {
        if(appKey == null){
            appKey = mMainComponentName;
        }
        if (appKey == null){
            return;
        }
        if(mReactRootView != null
                && isRunning==0//正在 onResume
                && getPlainActivity().getWindow().peekDecorView()!=null  //排除还没 resum
                && isCurrentActivity()){//当前activity
            onPause();
        }
        if (mReactRootView != null) {
            mReactRootView.unmountReactApplication();
            mProRootView = mReactRootView;
        }
        mReactRootView = createRootView();
        mReactRootView.startReactApplication(
                getReactNativeHost().getReactInstanceManager(),
                mMainComponentName = appKey,
                getLaunchOptions());
        if(isRunning==1//已经onPause了
                && getPlainActivity().getWindow().peekDecorView()!=null){//排除还没 resum
            onResume();
        }else if(!isCurrentActivity()){//第一个页面一开始并没有加载 rn 导致 currentActivity为空，所以这里调一下 onResume
            onResume();
        }
//        getPlainActivity().setContentView(mReactRootView);
    }

    protected void onPause() {
        isRunning = 1;
        if (getReactNativeHost().hasInstance()&&getReactNativeHost().getReactInstanceManager().getCurrentReactContext()!=null) {
            getReactNativeHost().getReactInstanceManager().onHostPause(getPlainActivity());
        }
    }

    protected void onResume() {
        isRunning = 0;
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onHostResume(
                    getPlainActivity(),
                    (DefaultHardwareBackBtnHandler) getPlainActivity());
        }

        if (mPermissionsCallback != null) {
            mPermissionsCallback.invoke();
            mPermissionsCallback = null;
        }
    }

    protected void onDestroy() {
        if (mReactRootView != null) {
            mReactRootView.unmountReactApplication();
            mReactRootView = null;
            mProRootView = null;
        }
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onHostDestroy(getPlainActivity());
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager()
                    .onActivityResult(getPlainActivity(), requestCode, resultCode, data);
        }
    }

    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
            if (keyCode == KeyEvent.KEYCODE_MENU) {
                getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
                return true;
            }
            boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer)
                    .didDoubleTapR(keyCode, getPlainActivity().getCurrentFocus());
            if (didDoubleTapR) {
                getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
                return true;
            }
        }
        return false;
    }

    public boolean onBackPressed() {
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onBackPressed();
            return true;
        }
        return false;
    }

    public boolean onNewIntent(Intent intent) {
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
            return true;
        }
        return false;
    }

    @TargetApi(Build.VERSION_CODES.M)
    public void requestPermissions(
            String[] permissions,
            int requestCode,
            PermissionListener listener) {
        mPermissionListener = listener;
        getPlainActivity().requestPermissions(permissions, requestCode);
    }

    public void onRequestPermissionsResult(
            final int requestCode,
            final String[] permissions,
            final int[] grantResults) {
        mPermissionsCallback = new Callback() {
            @Override
            public void invoke(Object... args) {
                if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
                    mPermissionListener = null;
                }
            }
        };
    }

    private Context getContext() {
        if (mActivity != null) {
            return mActivity;
        }
        return Assertions.assertNotNull(mFragmentActivity);
    }

    protected Activity getPlainActivity() {
        return ((Activity) getContext());
    }

    protected ReactRootView getReactRootView() {
        return mReactRootView;
    }

    //=============================================================
    private int isRunning = -1;
    private ReactRootView mProRootView = null;
    private Bundle mLaunchOptions;
    private boolean isCurrentActivity(){
        if (getReactNativeHost().hasInstance() && getReactNativeHost().getReactInstanceManager().getCurrentReactContext()!=null) {
            return getReactNativeHost().getReactInstanceManager().getCurrentReactContext().getCurrentActivity() == getPlainActivity();
        }else{
            return false;
        }
    }
    public ReactRootView getmProRootView(){
        return mProRootView;
    }

    public void setLaunchOptions(Bundle mLaunchOptions) {
        this.mLaunchOptions = mLaunchOptions;
    }

    @Nullable
    public String getMainComponentName() {
        return mMainComponentName;
    }
}
